using Gameplay.PVE.Config;
using Gameplay.PVE.Data;
using Gameplay.PVE.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using GameFramework.Battle.Core;
using NpcFramework;
using OWL.Rendering.HRP;
using UnityEngine;
using UnityEngine.Rendering;
using Yoozoo.Gameplay.Common;
using Yoozoo.Gameplay.RTS;
using Yoozoo.Gta.Common;
using Yoozoo.HRP.Runtime;
using Yoozoo.Manager;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Yoozoo.Mars.Got;
using Object = UnityEngine.Object;
using Yoozoo.Framework.Managers;

namespace Gameplay.PVE
{
    public class PveResourceManager
    {
        public enum EPveResType
        {
            Default = 0,
            Model = 1,
            Map = 2,
            MapData = 3,
            Building = 4,
            Pointer = 5,
            SkillEffect = 6,
            Drop = 7,
            Bullet = 8,
            UI = 9,
            Movie = 10,
            Director = 11,
            NavmeshPlane = 12,
            Camera = 13,
            Timeline = 14,
            Hud = 15,
            Mat = 16,
            People = 17,
            Texture = 18,
            Npc = 19,
            LightingSetting = 20,
            Music = 21,
            RenderSetting = 22,
            Car = 23,
            RpgScene = 24,
            GuideUseNpc = 25,
        }

        private static PveResourceManager instance;
        private ResLoader _resLoader;
        private PveSceneResourceManager _sceneResourceManager;
        private float eachAssetPercent;
        public bool IsReady = false;
        private List<ResLoader> lightMapLoader = new List<ResLoader>();
        private int loadingCount;
        private float loadingPercent;
        private GameObject loadingPrefab;
        private float loadStartTime;
        private ResLoader mapLoader;
        private Dictionary<int, Material> matDic = new Dictionary<int, Material>();
        private ResLoader matResLoader;
        private ResLoader camResLoader;
        private ResLoader pathMgrLoader;
        private ResLoader PeopleResLoader;
        private ResLoader textureLoader;
        
        private Texture2D miniMapTexture;
        private Dictionary<int, PveMapData> pveMapDataDic = new Dictionary<int, PveMapData>();
        private PveResourcePool resourcePool;
        private GameObject resRoot;
        private Dictionary<int, RpgLevelData> rpgLevelDataDic = new Dictionary<int, RpgLevelData>();
        private GameObject lightingObj;
        private GameObject shaderSetting;
        private Volume postEffectObj;
        private GameObject aStarRoot;
        private GameObject pveNpcFrameworkMgrObj;
        private GameObject pveTrafficLight;
        private bool isLoadedMap = false;
        private bool isLoadedMat = false;
        private GameObject camera;
        private GameObject rpgCamera;
        public static PveResourceManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new PveResourceManager();
                    Debug.LogWarning("创建一个PveResourceManager....");
                    // 初始化因在相机之前
                    NFMgr.NfConstValue = new NFConstValue();
                }

                return instance;
            }
        }
        public void Initialize(Action onLoadOver)
        {
            UnityEngine.Debug.Log("pveScene:  PveResourceManager..Initialize");
            resRoot = new GameObject("[PveResRoot]");
            resRoot.SetActive(false);
            _resLoader = ResLoader.Alloc();
            float loadStartTime = TimeManager.logicTime;
            PveManager.Instance.UpdateLoadingProgress(0.5f,"资源初始化");
            loadingPercent = 0;
            loadingCount = 0;
            _sceneResourceManager = new PveSceneResourceManager();
            _sceneResourceManager.Initialize();
            resourcePool = new PveResourcePool();
            resourcePool.Initialize(EPveResType.Model, resRoot.transform, _resLoader);

            GameObject pathRoot = new GameObject("[PathRoot]");

            //LoadPveResource(onLoadOver, loadStartTime);
            LoadAFKNeedResource(30000000, PveUtils.deckHeroes, new List<int>(){});
        }

        public void UpdatePveHeroes(Action action)
        {
            LoadAFKNeedResource(30000000, PveUtils.deckHeroes, new List<int>(){},action);
        }
        
        public List<int> GetRPGEnemyList(int levelId)
        {
            var monsterConfig = PveUtils.GetRpgLevelMonsterConfig(levelId);
            if (monsterConfig.level_id_count!=null)
            {
                HashSet<int> enemyList = new HashSet<int>();
                foreach (var monsterHeroId in monsterConfig.level_id_count)
                {
                    enemyList.Add(monsterHeroId);
                }
                return enemyList.ToList();
            }
            else
            {
                return null;
            }
        }

        public List<int> GetFirstRpgWaveEnemy(int levelId)
        {
            var monsterConfig = PveUtils.GetRpgLevelMonsterConfig(levelId);
            if (monsterConfig.level_id_count != null)
            {
                HashSet<int> enemyList = new HashSet<int>();
                for (int i = 0; i < monsterConfig.level_id_count.Count; i++)
                {
                    int wave = 0;
                    if (monsterConfig.monster_wave.Count > i)
                    {
                        wave = monsterConfig.monster_wave[i];
                    }

                    float time = 0;
                    if (monsterConfig.monster_time.Count > i)
                    {
                        time = monsterConfig.monster_time[i];
                    }
                    if (wave == 0 && time == 0)
                    {
                        enemyList.Add(monsterConfig.level_id_count[i]);
                    }
                }
                return enemyList.ToList();
            }

            return null;
        }

        private ResLoader rpgLightMapLoader;
        private LightmapData[] rpgLightMaps;
        private int restLightMapCount;
        private LightmapData[] hangingLightMaps;
        private GameObject rpgBattleScene;
        private bool isRpgSceneSwitchComplete;

        public void CheckIsRpgSceneReady()
        {
            if (rpgBattleScene != null && restLightMapCount == 0 && isRpgSceneSwitchComplete)
            {
                hangingLightMaps = LightmapSettings.lightmaps;
                //LightmapSettings.lightmaps = rpgLightMaps;
                rpgBattleScene.SetActive(true);
                PveManager.Instance.HideMap();
                PveCameraManager.Instance.PveToRpgDeck();
                rpgBattleScene.transform.position = PveManager.Instance.GetRpgStageCenterPosition() + new Vector3(-60.74f,-0.13f,-36.65f);
                HRPHelper.ClearRenderScene();
                HRPHelper.EnableBaseScene(HRPHelper.RpgRenderScene);
                SetRimLightCameraDir setRimLightCameraDir = 
                    HRPHelper.RpgRenderScene.transform.GetComponentInChildren<SetRimLightCameraDir>();
                if (setRimLightCameraDir!=null)
                {
                    setRimLightCameraDir.SceneCamera =
                        PveResourceManager.Instance.GetRpgCamera().GetComponentInChildren<Camera>();
                }
            }
        }

        public void RpgSceneSwitchComplete()
        {
            isRpgSceneSwitchComplete = true;
            CheckIsRpgSceneReady();
        }
        
        private Action<GameObject> GetLoadOverAction(int type,int id)
        {
            if (type == (int) EPveResType.RpgScene)
            {
                return (o) =>
                {
                    rpgLightMapLoader = ResLoader.Alloc();
                    rpgBattleScene = GetResource(EPveResType.RpgScene,id);
                    rpgBattleScene.transform.SetParent(PveScene.pveRootTrans);
                    var data = rpgBattleScene.GetComponent<RpgBattleSceneData>();
                    data.lightingSetting.SetActive(false);
                    int count = data.lightMapPath.Count;
                    restLightMapCount = count * 2;
                    rpgLightMaps = new LightmapData[count];
                    
                    for (int i = 0; i < count; i++)
                    {
                        int index = i;
                        rpgLightMaps[index] = new LightmapData();
                        rpgLightMapLoader.Add2Load(data.lightMapPath[i], (success, path, obj) =>
                        {
                            if (success)
                            {
                                var texture = obj as Texture2D;
                                rpgLightMaps[index].lightmapColor = texture;
                            }
                            restLightMapCount--;
                        });
                        rpgLightMapLoader.Add2Load(data.lightMapDirPath[i], (success, path, obj) =>
                        {
                            if (success)
                            {
                                var texture = obj as Texture2D;
                                rpgLightMaps[index].lightmapDir = texture;
                            }
                            restLightMapCount--;
                        });
                    }

                    for (int i = 0; i < data.meshList.Count; i++)
                    {
                        data.meshList[i].lightmapIndex = data.lightMapIndexList[i];
                        data.meshList[i].lightmapScaleOffset = data.lightMapOffsetList[i];
                    }
                    rpgBattleScene.SetActive(false);
                    rpgLightMapLoader.Load();
                };
            }
            if (type != (int)EPveResType.Model)
            {
                return null;
            }
            return (o) =>
            {
                /*Material modelFlashMat;
                Material modelShadowMat;
                matDic.TryGetValue((int) EPveMaterialType.modelShadowMat, out modelShadowMat);
                matDic.TryGetValue((int) EPveMaterialType.modelFlashMat, out modelFlashMat);
                //临时添加变色材质
                var meshes = o.GetComponentsInChildren<SkinnedMeshRenderer>();
                if (meshes.Length > 0)
                {
                    for (int i = 0; i < meshes.Length; i++)
                    {
                        var mesh = meshes[i];
                        var mats = new Material[mesh.materials.Length + 1];
                        for (int j = 0; j < mesh.materials.Length; j++) //替换描边
                        {
                            mats[j] = mesh.materials[j];
                        }
                        //mats[mesh.materials.Length] = modelShadowMat;
                        mats[mesh.materials.Length] = new Material(modelFlashMat);
                        mesh.materials = mats;
                    }
                }
                var m_meshed = o.GetComponentsInChildren<MeshRenderer>();
                for (int i = 0; i < m_meshed.Length; i++)
                {
                    var mesh = m_meshed[i];
                    var mats = new Material[mesh.materials.Length + 1];
                    for (int j = 0; j < mesh.materials.Length; j++)
                    {
                        mats[j] = mesh.materials[j];
                    }

                    //mats[mesh.materials.Length] = modelShadowMat;
                    mats[mesh.materials.Length] = new Material(modelFlashMat);
                    mesh.materials = mats;
                }*/
            };
        }
        public GameObject GetPVECamera()
        {
            return camera;
        }

        public GameObject GetRpgCamera()
        {
            return rpgCamera;
        }

        private class RpgHeroResourceInfo
        {
            public int id;
            public List<int> needLoadResource;
        }
        private Dictionary<int,RpgHeroResourceInfo> heroResources = new Dictionary<int, RpgHeroResourceInfo>();

        private HashSet<int> rpgBattleNewResource = new HashSet<int>();
        
        private void AddHeroResources(int heroId, HashSet<int> hashSet,HashSet<int> totalHashSet)
        {
            if (heroResources.ContainsKey(heroId))
            {
                return;
            }
            Debug.Log("注册英雄"+heroId);
            var heroResourceInfo = new RpgHeroResourceInfo();
            heroResourceInfo.id = heroId;
            heroResourceInfo.needLoadResource = new List<int>();
            heroResources.Add(heroId,heroResourceInfo);
            
            foreach (var resId in hashSet)
            {
                totalHashSet.Add(resId);
                //if (!resourcePool.HasRegister(resId))
                {
                    heroResourceInfo.needLoadResource.Add(resId);
                }
            }
        }

        public bool IsHeroResourceReady(int heroId)
        {
            if (heroResources.TryGetValue(heroId, out var resInfo))
            {
                for (int i = 0; i < resInfo.needLoadResource.Count; i++)
                {
                    var id = resInfo.needLoadResource[i];
                    if (!resourcePool.IsResReady(id))
                    {
                        Debug.LogError("资源未加载完毕 " + id);
                        return false;
                    }
                }

                return true;
            }
            Debug.LogError("尚未注册英雄资源 " + heroId );
            return false;
        }

        private void TryAddToRpgBattleNewResource(int resId)
        {
            if (resourcePool.HasRegister(resId))
            {
                return;
            }
            rpgBattleNewResource.Add(resId);
        }
        
        public void LoadMonster(int heroId)
        {
            if (heroResources.ContainsKey(heroId))
            {
                return;
            }
            var hashSet = new HashSet<int>();
            CalMonsterNeedResIds(heroId,hashSet);
            AddHeroResources(heroId,hashSet,hashSet);
            foreach (var resId in hashSet)
            {
                var resourceCfg = PveUtils.GetRpgResourceConfig(resId);
                if (resourceCfg != null)
                {
                    TryAddToRpgBattleNewResource(resId);
                    Instance.resourcePool.AddResourceAndLoad(resId,resourceCfg.path, resourceCfg.poolNum, (EPveResType)resourceCfg.type);
                }
            }
            Instance.resourcePool.Load(null);
        }

        public void BackToHangScene()
        {
            if (rpgBattleScene != null)
            {
                rpgBattleScene.SetActive(false);
            }

            LightmapSettings.lightmaps = hangingLightMaps;
        }

        public void SetRpgBattleSceneActive(bool active)
        {
            if (rpgBattleScene != null)
            {
                rpgBattleScene.SetActive(active);
            }
        }
        
        public void UnloadRpgResource()
        {
            if (!PveGlobalVlues.PreloadRpgScene)
            {
                Instance.resourcePool.UnloadRes(GetResConfigId(EPveResType.RpgScene, PveGlobalVlues.RpgSceneId));
                rpgBattleScene = null;
            }
           
            UnloadAllHero();
            if (rpgBattleBg)
            {
                Object.DestroyImmediate(rpgBattleBg);
                rpgBattleBg = null;
            }

            if (lastRpgBattleBg)
            {
                Object.DestroyImmediate(lastRpgBattleBg);
                lastRpgBattleBg = null;
            }

            lastRpgBattleBgPath = null;
            if (textureLoader != null)
            {
                textureLoader.Recycle2Cache();
                textureLoader = null;
            }
        }
        
        
        
        public void LoadTest()
        {
            textureLoader = ResLoader.Alloc();
            /*var list = new List<int> { 510110,510111,510120,510121,510210,510211,510220,510221,510310,510311,510320,510321,510410,510411,510420,510421};
            for (int i = 0; i < list.Count; i++)
            {
                var path = PveUtils.GetRpgResourceConfig(GetResConfigId(EPveResType.Model,list[i])).path;
                textureLoader.Add2Load(path + ".prefab", (success, name, asset) => { });
            }*/
            for (int i = 1; i <= 7; i++)
            {
                var path = "Assets/ResourcesAssets/Pve/Textures/tex_pveSceneNewBg" + i + ".png";
                textureLoader.Add2Load(path, (success, name, asset) => { });
            }
            //var path = "Assets/ResourcesAssets/Pve/Prefabs/Others/PveDeckCanvas.prefab";
            //textureLoader.Add2Load(path, (success, name, asset) => { });
            textureLoader.Load();
        }

        public void UnloadAllHero()
        {
            foreach (var id in rpgBattleNewResource)
            {
                Instance.resourcePool.UnloadRes(id);
            }
            rpgBattleNewResource.Clear();
            heroResources.Clear();
            GameHelper.ForceRelease();
        }
        
        
        /// <summary>
        /// 加载RPG必须要的资源
        /// </summary>
        /// <param name="sceneId"></param>
        /// <param name="heroList"></param>
        /// <param name="enemyList"></param>
        /// <param name="loadOverAction"></param>
        public void LoadRPGNeedResource(int sceneId,List<int> heroList, List<int> enemyList,Action loadOverAction)
        {
            isRpgSceneSwitchComplete = false;
            Debug.Log("开始加载Rpg资源");
            HashSet<int> hashSet = new HashSet<int>();
            
            foreach (var heroId in heroList)
            {
                var heroHashSet = new HashSet<int>();
                CalHeroNeedResIds(heroId, heroHashSet);
                AddHeroResources(heroId, heroHashSet,hashSet);
            }
            foreach (var enemyId in enemyList)
            {
                var specialConfig = PveUtils.GetRpgSpecialObjectConfig(enemyId);
                if (specialConfig == null)
                {
                    var heroHasSet = new HashSet<int>();
                    CalMonsterNeedResIds(enemyId, heroHasSet);
                    AddHeroResources(enemyId, heroHasSet,hashSet);
                }
                else
                {
                    var heroHasSet = new HashSet<int>();
                    CalSpecialObjectNeedResIds(specialConfig, hashSet);
                    AddHeroResources(enemyId, heroHasSet,hashSet);
                }
            }

            if (PveGlobalVlues.specificEnemy != 0)
            {
                CalMonsterNeedResIds(PveGlobalVlues.specificEnemy, hashSet);
            }
            CalSpecialNeedResIds(hashSet);

            
            

            CalObstacleIds(hashSet);
            
            int battle_model_res = 1;
            var rpgLevelMonster = PveUtils.GetRpgLevelMonsterConfig(PveManager.Instance.RpgLevelId);
            if (rpgLevelMonster != null)
            {
                battle_model_res = rpgLevelMonster.battle_model_res;
            }
            

            var battle_lighting_setting = GetResConfigId(EPveResType.LightingSetting, battle_model_res);
            if (PveUtils.GetRpgResourceConfig(battle_lighting_setting) == null)
            {
                battle_lighting_setting = GetResConfigId(EPveResType.LightingSetting, 1);
            }
            hashSet.Add(battle_lighting_setting);

            var battle_music = GetResConfigId(EPveResType.Music, battle_model_res);
            if (PveUtils.GetRpgResourceConfig(battle_music) == null)
            {
                battle_music = GetResConfigId(EPveResType.Music, 1);
            }

            hashSet.Add(battle_music);

            var renderSetting = GetResConfigId(EPveResType.RenderSetting, 1);
            hashSet.Add(renderSetting);

            if (!PveGlobalVlues.PreloadRpgScene && !PveGlobalVlues.RpgFightUseTextureBg)
            {
                var rpgScene = GetResConfigId(EPveResType.RpgScene, PveGlobalVlues.RpgSceneId);
                hashSet.Add(rpgScene);
            }

            
            foreach (var id in hashSet)
            {
                if (!resourcePool.HasRegister(id))
                {
                    rpgBattleNewResource.Add(id);
                }
                var resourceCfg = PveUtils.GetRpgResourceConfig(id);
                if (resourceCfg != null)
                {
                    Action<GameObject> onLoadOver = GetLoadOverAction(resourceCfg.type,resourceCfg.subid);
                    resourcePool.AddResource(id, resourceCfg.path, resourceCfg.poolNum, (EPveResType)resourceCfg.type,onLoadOver);
                }
            }
            
            LoadRPGMustLoadResource(sceneId, (() =>
            {
                StartLoad(() =>
                {
                    Debug.Log("真正的rpg资源加载完成");
                    if (PveGlobalVlues.RpgFightUseTextureBg)
                    {
                        textureLoader = ResLoader.Alloc();
                        var battle_model_res_real_id = GetResConfigId(EPveResType.Texture,battle_model_res);
                        var path = PveUtils.GetRpgResourceConfig(battle_model_res_real_id).path+".png";
                        if (lastRpgBattleBgPath != path)
                        {
                            lastRpgBattleBg = rpgBattleBg;
                            lastRpgBattleBgPath = path;
                            textureLoader.Add2Load(path, (b,n,a) =>
                            {
                                Debug.Log("背景图加载完成");
                                var texture = a as Texture2D;
                                rpgBattleBg = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0, 0));
                                loadOverAction?.Invoke();
                            }).Load();
                        }
                        else
                        {
                            Debug.Log("背景图不用重新加载");
                            loadOverAction?.Invoke();
                        }
                    }
                    else
                    {
                        loadOverAction?.Invoke();
                    }
                });
            }));
        }

        private Sprite rpgBattleBg;
        private Sprite lastRpgBattleBg;

        private string lastRpgBattleBgPath;

        public static void DestroyLastRpgBattlePath()
        {
            if (instance.lastRpgBattleBg != null)
            {
                Object.Destroy(instance.lastRpgBattleBg);
                instance.lastRpgBattleBg = null;
            }
        }
        
        public static Sprite GetRpgBattleBg()
        {
            return instance.rpgBattleBg;
        }

        /// <summary>
        /// 加载挂机必须的资源
        /// </summary>
        /// <param name="sceneId"></param>
        /// <param name="loadOverAction"></param>
        private void LoadRPGMustLoadResource(int sceneId,Action loadOverAction)
        {
            PreloadCamera(() =>
            {
                Debug.Log("camera加载成功");
                PreloadPathManager(() =>
                {
                    _sceneResourceManager.LoadScene(sceneId, resRoot, (() =>
                    {
                        PreloadMap(() =>
                        {
                            Debug.Log("mapData加载成功");
                            LoadMaterials(() =>
                            {
                                Debug.Log("material加载成功");
                                PreloadHud();
                                PreloadPointer();
                                //PreloadDirector();
                                PreloadUI();
                                loadOverAction.Invoke();
                            });
                        });
                    }),false);
                });
            });
        }
        /// <summary>
        /// 预加载挂机所需要的资源
        /// </summary>
        /// <param name="sceneId">场景id</param>
        /// <param name="heroList">自己英雄id列表</param>
        /// <param name="enemyList">敌人的id列表</param>
        /// <param name="loadOverAction"></param>
        public void LoadAFKNeedResource(int sceneId, List<int> heroList,List<int> enemyList,Action loadOverAction = null)
        {
            UnityEngine.Debug.Log("pveScene:  pveResManager:LoadAFKNeedResource");
            HashSet<int> hashSet = new HashSet<int>();
            //CalHeroNeedResIds(41004, hashSet);
            /*foreach (var heroId in heroList)
            {
                CalHeroNeedResIds(heroId, hashSet);
            }
            foreach (var enemyId in enemyList)
            {
                CalMonsterNeedResIds(enemyId, hashSet);
            }*/
            /*CalSpecialNeedResIds(hashSet);

            if (PveGlobalVlues.PreloadRpgScene && !PveGlobalVlues.RpgFightUseTextureBg)
            {
                var rpgScene = GetResConfigId(EPveResType.RpgScene, PveGlobalVlues.RpgSceneId);
                hashSet.Add(rpgScene);
            }
            
            
            foreach (var id in hashSet)
            {
                var resourceCfg = PveUtils.GetRpgResourceConfig(id);
                Action<GameObject> onLoadOver = GetLoadOverAction(resourceCfg.type,resourceCfg.subid);
                resourcePool.AddResource(id, resourceCfg.path, resourceCfg.poolNum,(EPveResType)resourceCfg.type,onLoadOver);
                if (id == 10000997)
                {
                    resourcePool.AddResource(id, resourceCfg.path, resourceCfg.poolNum,(EPveResType)resourceCfg.type,onLoadOver);
                }
            }*/
            CalSpecialAfkNeedResIds(hashSet);
            foreach (var id in hashSet)
            {
                var resourceCfg = PveUtils.GetRpgResourceConfig(id);
                Action<GameObject> onLoadOver = GetLoadOverAction(resourceCfg.type,resourceCfg.subid);
                resourcePool.AddResource(id, resourceCfg.path, resourceCfg.poolNum,(EPveResType)resourceCfg.type,onLoadOver);
                if (id == 10000997)
                {
                    resourcePool.AddResource(id, resourceCfg.path, resourceCfg.poolNum,(EPveResType)resourceCfg.type,onLoadOver);
                }
            }
            PreLoadPeopleAndCarRes();
            PveManager.Instance.UpdateLoadingProgress(0.55f,"PreLoadPeopleAndCarRes");
            LoadAFKMustLoadResource(sceneId, (() =>
            {
                StartLoad(() =>
                {
                    Debug.Log("加载对象池总耗时" + (TimeManager.logicTime - loadStartTime));
                    PveManager.Instance.UpdateLoadingProgress(0.9f,"加载AFK必须的资源完成");
                    loadOverAction?.Invoke();
                    PveScene.EnterPveBattle();
                    PveManager.Instance.UpdateLoadingProgress(0.95f,"EnterPveBattle");
                    // TODO 需要整理当前场景执行流程，这是简易做法
                    Timers.inst.Add(2,1,(o =>
                    {
                        PveCameraManager.Instance.InitHCamera();
                        PveManager.Instance.UpdateLoadingProgress(1f,"加载完毕");
                    }));
                });
            }));
        }

        public void LoadDeckHero(int modelId,Action onloadOver)
        {
            var resourceCfg = PveUtils.GetRpgResourceConfig(GetResConfigId(EPveResType.Model, modelId));
            TryAddToRpgBattleNewResource(resourceCfg.id);
            resourcePool.AddResourceAndLoad(resourceCfg.id, resourceCfg.path, resourceCfg.poolNum, (EPveResType) resourceCfg.type,
                (o)=>
                {
                    onloadOver?.Invoke();
                });
            resourcePool.Load(null);
        }
        
        /// <summary>
        /// 有些写死的加在这里
        /// </summary>
        /// <param name="needLoadId"></param>
        private void CalSpecialNeedResIds(HashSet<int> needLoadId)
        {

            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, (int)ESkillEffect.hitObstacleCar));
            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, (int)ESkillEffect.hitRoleHead));
            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, (int)ESkillEffect.hitObstacleGround));
            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, (int)ESkillEffect.hitRoleHeadGround));
            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, (int)ESkillEffect.hitRole));
            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect,13));
            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, 24));
            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, 25));
            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, 100));
            needLoadId.Add(GetResConfigId(EPveResType.Hud, 11));
            needLoadId.Add(GetResConfigId(EPveResType.Hud, 13));
            needLoadId.Add(GetResConfigId(EPveResType.Hud, 14));
            needLoadId.Add(GetResConfigId(EPveResType.Hud, 15));
            needLoadId.Add(GetResConfigId(EPveResType.Hud, 17)); //pveDeckCircle
            needLoadId.Add(GetResConfigId(EPveResType.Hud, 18)); //pveDeckLevel
            needLoadId.Add(GetResConfigId(EPveResType.Hud, 19)); //pveDeckLoading
            needLoadId.Add(GetResConfigId(EPveResType.UI, 1));
#if UNITY_EDITOR
            needLoadId.Add(GetResConfigId(EPveResType.UI, 11));
#endif
            needLoadId.Add(GetResConfigId(EPveResType.UI, 30));
            needLoadId.Add(GetResConfigId(EPveResType.UI, 31));
            needLoadId.Add(GetResConfigId(EPveResType.UI, 32));
            //主角
            needLoadId.Add(GetResConfigId(EPveResType.Model, 6666));
 
            needLoadId.Add(GetResConfigId(EPveResType.Music, 101));
            needLoadId.Add(GetResConfigId(EPveResType.Music, 102));
            //镜头timeline
            needLoadId.Add(GetResConfigId(EPveResType.Timeline, 1));

            needLoadId.Add(GetResConfigId(EPveResType.GuideUseNpc, 1));
        }

        private void CalSpecialAfkNeedResIds(HashSet<int> needLoadId)
        {
            //主角
            needLoadId.Add(GetResConfigId(EPveResType.Model, 6666));
 
            needLoadId.Add(GetResConfigId(EPveResType.Music, 101));
            needLoadId.Add(GetResConfigId(EPveResType.Music, 102));
            needLoadId.Add(GetResConfigId(EPveResType.UI, 1));
            //镜头timeline
            needLoadId.Add(GetResConfigId(EPveResType.Timeline, 1));

            needLoadId.Add(GetResConfigId(EPveResType.GuideUseNpc, 1));
        }
        
        /// <summary>
        /// 障碍物
        /// </summary>
        /// <param name="needLoadId"></param>
        private void CalObstacleIds(HashSet<int> needLoadId)
        {
            needLoadId.Add(GetResConfigId(EPveResType.Model,100));
        }


        /// <summary>
        /// 加载挂机必须的资源
        /// </summary>
        /// <param name="sceneId"></param>
        /// <param name="loadOverAction"></param>
        private void LoadAFKMustLoadResource(int sceneId, Action loadOverAction)
        {
            PreloadCamera(() =>
            {
                PveManager.Instance.UpdateLoadingProgress(0.6f,"PreLoadPeopleAndCarRes");
                UnityEngine.Debug.Log("pveScene:  PreloadCamera..Complete");
                PreloadPathManager(() =>
                {
                    PveManager.Instance.UpdateLoadingProgress(0.65f,"PreloadPathManager");
                    UnityEngine.Debug.Log("pveScene:  PreloadPathManager..Complete");
                    _sceneResourceManager.LoadScene(sceneId, resRoot, (() =>
                    {
                        PveManager.Instance.UpdateLoadingProgress(0.7f,"sceneResourceManager LoadScene");
                        UnityEngine.Debug.Log("pveScene:  PreloadPathManager..LoadScene");
                        PreloadMap(() =>
                        {
                            PveManager.Instance.UpdateLoadingProgress(0.75f,"PreloadMap");
                            UnityEngine.Debug.Log("pveScene:  PreloadPathManager..PreloadMap");
                            LoadMaterials(() =>
                            {
                                PveManager.Instance.UpdateLoadingProgress(0.8f,"LoadMaterials");
                                UnityEngine.Debug.Log("pveScene:  PreloadPathManager..LoadMaterials");
                                loadOverAction.Invoke();
                            });

                        });
                    }),true);
                });
            });
        }
        
        /// <summary>
        /// 计算特殊物体需要以来的资源id
        /// </summary>
        /// <param name="config"></param>
        /// <param name="needLoadId"></param>
        public void CalSpecialObjectNeedResIds(RpgSpecialObjectConfig config, HashSet<int> needLoadId)
        {
            if (config.model_id != 0)
            {
                needLoadId.Add(GetResConfigId(EPveResType.Model, config.model_id));
            }
        }

        /// <summary>
        /// 计算一个英雄所依赖的资源id
        /// </summary>
        /// <param name="heroId"></param>
        /// <param name="needLoadId"></param>
        public void CalHeroNeedResIds(int heroId, HashSet<int> needLoadId)
        {
            var heroConfig = PveUtils.GetRpgModelConfig(heroId);
            needLoadId.Add(GetResConfigId(EPveResType.Model, heroConfig.res_id));
            var battleConfig = PveUtils.GetExternalHeroConfig(heroId);
            if (battleConfig.rpg_normal_attack_id!=0)
            {
                AddSkillIdNeedRes(battleConfig.rpg_normal_attack_id, needLoadId);
            }

            /*if (battleConfig.rpg_passive_skill_id!=null)
            {
                foreach (var passiveId in battleConfig.rpg_passive_skill_id)
                {
                    AddSkillIdNeedRes(passiveId, needLoadId);
                }
            }
            if (battleConfig.rpg_skill_id != 0)
            {
                AddSkillIdNeedRes(battleConfig.rpg_skill_id, needLoadId);
            }*/

            var heroData = PveUtils.GetPveHeroData(heroId);
            if (heroData != null)
            {
                AddSkillIdNeedRes(heroData.skillInitiative,needLoadId);
                foreach (var passive in heroData.passiveSkillLevels)
                {
                    AddSkillIdNeedRes(passive.x, needLoadId);
                }
            }

            if (heroConfig.skill_model_id != 0)
            {
                needLoadId.Add(GetResConfigId(EPveResType.Model, heroConfig.skill_model_id));
            }
        }

        /// <summary>
        /// 计算一个野怪所依赖的资源id
        /// </summary>
        /// <param name="heroId"></param>
        /// <param name="needLoadId"></param>
        public void CalMonsterNeedResIds(int heroId, HashSet<int> needLoadId)
        {
            var battleConfig = PveUtils.GetRpgMonsterConfig(heroId);
            var heroConfig = PveUtils.GetRpgModelConfig(battleConfig.model_id);
            needLoadId.Add(GetResConfigId(EPveResType.Model, heroConfig.res_id));
            if (battleConfig.rpg_normal_attack_id!=0)
            {
                AddSkillIdNeedRes(battleConfig.rpg_normal_attack_id, needLoadId);
            }

            if (battleConfig.rpg_passive_skill_id!=null)
            {
                foreach (var passiveId in battleConfig.rpg_passive_skill_id)
                {
                    AddSkillIdNeedRes(passiveId, needLoadId);
                }
            }
            if (battleConfig.rpg_skill_id != 0)
            {
                AddSkillIdNeedRes(battleConfig.rpg_skill_id, needLoadId);
            }
            if (heroConfig.skill_model_id != 0)
            {
                needLoadId.Add(GetResConfigId(EPveResType.Model, heroConfig.skill_model_id));
            }

        }

        /// <summary>
        /// 计算技能所依赖的资源
        /// </summary>
        /// <param name="skillId"></param>
        /// <param name="needLoadId"></param>
        private void AddSkillIdNeedRes(int skillId,HashSet<int> needLoadId)
        {
            var skillConfig = PveUtils.GetSkillConfig(skillId);
            if (skillConfig != null)
            {
                var childSkills = skillConfig.child_skills;
                for (int i = 0; i < childSkills.Count; i++)
                {
                    AddSkillIdNeedRes(childSkills[i],needLoadId);
                }
                
                var bullets = skillConfig.bullets;
                if (bullets != null)
                {
                    foreach (var bulletsVector3 in bullets)
                    {
                        if (bulletsVector3.y != 0)
                        {
                            AddBulletsNeedRes((int)bulletsVector3.y, needLoadId);
                        }
                    }

                    if (bullets.Count > 0)
                    {
                        var bulletConfig = PveUtils.GetSkillBulletConfig(bullets[0].y);
                        if (bulletConfig != null)
                        {
                            if (bulletConfig.director_type >= 0)
                            {
                                needLoadId.Add(GetResConfigId(EPveResType.Director, PveTargetSearchHelper.GetDirectorResourceByBulletConfig(bulletConfig)));
                            }
                            
                            if (bulletConfig.director_args != null)
                            {
                                if (bulletConfig.director_args.ContainsKey("distance"))
                                {
                                    needLoadId.Add(GetResConfigId(EPveResType.Director, 4));
                                }
                                else if (bulletConfig.director_args.ContainsKey("width"))
                                {
                                    needLoadId.Add(GetResConfigId(EPveResType.Director, 2));
                                }
                            }
                        }
                    }
                }

                var effects = skillConfig.effects;
                if (effects!=null)
                {
                    foreach (var effectVector3 in effects)
                    {
                        if (effectVector3.y != 0)
                        {
                            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, (int)effectVector3.y));
                        }
                    }
                }

                if (skillConfig.summon_id != 0)
                {
                    var summonConfig = PveUtils.GetRpgSummonConfig(skillConfig.summon_id);
                    if (summonConfig != null)
                    {
                        if (summonConfig.type == 0)
                        {
                            var monsterConfig = PveUtils.GetRpgMonsterConfig(summonConfig.summon_id);
                            var heroConfig = PveUtils.GetRpgModelConfig(monsterConfig.model_id);
                            var heroId = GetResConfigId(EPveResType.Model, heroConfig.res_id);
                            if (!needLoadId.Contains(heroId))
                            {
                                CalMonsterNeedResIds(summonConfig.summon_id, needLoadId);
                            }
                        }
                        else if (summonConfig.type == 1)
                        {
                            var obstacleConfg = PveUtils.GetRpgObstacleConfig(summonConfig.summon_id);
                            if (obstacleConfg.res_id != 0)
                            {
                                needLoadId.Add(GetResConfigId(EPveResType.Model, obstacleConfg.res_id));
                            }

                            if (obstacleConfg.break_res_id != 0)
                            {
                                needLoadId.Add(GetResConfigId(EPveResType.Model, obstacleConfg.break_res_id));
                            }

                            if (obstacleConfg.hit_effect != 0)
                            {
                                needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, obstacleConfg.hit_effect));
                            }

                            if (obstacleConfg.dead_effect != 0)
                            {
                                needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, obstacleConfg.dead_effect));
                            }
                        }

                        if (summonConfig.summon_effect != 0)
                        {
                            needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, summonConfig.summon_effect));
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 计算子弹所依赖的资源
        /// </summary>
        /// <param name="bulletId"></param>
        /// <param name="needLoadId"></param>
        private void AddBulletsNeedRes(int bulletId, HashSet<int> needLoadId)
        {
            var bulletCfg = PveUtils.GetSkillBulletConfig(bulletId);
            if (bulletCfg!=null)
            {
                if (bulletCfg.model!=0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.Bullet, bulletCfg.model));
                }

                if (bulletCfg.static_model != 0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.Bullet, bulletCfg.static_model));
                }

                if (bulletCfg.destroy_effect_id!=0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, bulletCfg.destroy_effect_id));
                }

                if (bulletCfg.effect_id != 0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, bulletCfg.effect_id));
                }
                
                if (bulletCfg.hit_effect != 0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, bulletCfg.hit_effect));
                }

                if (bulletCfg.jump_effect != 0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, bulletCfg.jump_effect));
                }

                if (bulletCfg.trail_effect_id!=0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.Bullet, bulletCfg.trail_effect_id));
                }

                if (bulletCfg.bullet_case_effect_id != 0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.Bullet, bulletCfg.bullet_case_effect_id));
                }

                if (bulletCfg.elements!=null)
                {
                    foreach (var elementsId in bulletCfg.elements)
                    {
                        GetElementsNeedRes(elementsId, needLoadId);
                    }
                }
                if (bulletCfg.bullets != null)
                {
                    foreach (var generateBullets in bulletCfg.bullets)
                    {
                        AddBulletsNeedRes(generateBullets, needLoadId);
                    }
                }
            }
        }
        /// <summary>
        /// 计算element所依赖的资源
        /// </summary>
        /// <param name="elementsId"></param>
        /// <param name="needLoadId"></param>
        private void GetElementsNeedRes(int elementsId, HashSet<int> needLoadId)
        {
            var elementConfig = PveUtils.GetSkillElementConfig(elementsId);
            if (elementConfig != null)
            {
                if (elementConfig.effect!=0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, elementConfig.effect));
                }

                if (elementConfig.duration_effect!=0)
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, elementConfig.duration_effect));
                }
                
                if (elementConfig.element_param.TryGetValue("AddEffect",out var id))
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, id));
                }
                if (elementConfig.element_param.TryGetValue("FreeEffect",out var id2))
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, id2));
                }
                if (elementConfig.element_param.TryGetValue("DestroyEffect",out var id3))
                {
                    needLoadId.Add(GetResConfigId(EPveResType.SkillEffect, id3));
                }

                if (elementConfig.element_param.TryGetValue("TriggerSkill", out var skillId))
                {
                    AddSkillIdNeedRes(skillId,needLoadId);
                }
                
                if (elementConfig.element_param.TryGetValue("ChangeBulletNewId",out var newId))
                {
                    AddBulletsNeedRes(newId,needLoadId);
                }

                if (elementConfig.element_param.TryGetValue("SustainElement0", out var s0))
                {
                    GetElementsNeedRes(s0, needLoadId);
                }
            }
        }

        /// <summary>
        /// 根据类型和子id组装出rpg_resource_config表的主键
        /// </summary>
        /// <param name="pveResType"></param>
        /// <param name="subid"></param>
        /// <returns></returns>
        public int GetResConfigId(EPveResType pveResType, int subid)
        {
            if (pveResType == EPveResType.SkillEffect)
            {
                var config = PveUtils.GetRpgEffectConfig(subid);
                if (config != null)
                {
                    subid = config.res_id_h;
                }
            }
            return (int) pveResType * 10000000 + subid;
        }

        public static string[] tempPeopleRes = new[]
        {
            "Assets/ResourcesAssets/Prefabs/Character/PveAfk/npc01_M",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/npc02_M",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/npc03_M",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/NpcMale01",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/NpcMale04",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/NpcMale06",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/NpcMale08",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/NpcFamale02",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/NpcFamale03",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/NpcFamale05",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_01",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_02",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_03",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_04",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_05",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_06",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_07",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_08",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_09",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_10",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_11",
"Assets/ResourcesAssets/Prefabs/Character/PveAfk/Enemy_12"

        };

        public static int maxPeopleResCount;
        public static int maxCarResCount;
        private void PreLoadPeopleAndCarRes()
        {
            PeopleResLoader = ResLoader.Alloc();
            var list = PveUtils.GetRpgResourceConfigListByType(EPveResType.Npc);
            maxPeopleResCount = list.Count;
            foreach (var resourceCfg in list)
            {
                resourcePool.AddResource(resourceCfg.id, resourceCfg.path, resourceCfg.poolNum, (EPveResType)resourceCfg.type);
            }
            //汽车
            var carlist = PveUtils.GetRpgResourceConfigListByType(EPveResType.Car);
            maxCarResCount = carlist.Count;
            foreach (var resourceCfg in carlist)
            {
                resourcePool.AddResource(resourceCfg.id, resourceCfg.path, resourceCfg.poolNum, (EPveResType)resourceCfg.type);
            }
        }


        public static string GetHeroPath(int hero)
        {
            return Instance.GetRpgResourceFullPath(hero, false);
        }

        public static string GetBulletPath(int bullet)
        {
            return Instance.GetRpgResourceFullPath(Instance.GetResConfigId(EPveResType.Bullet, bullet), false);
        }

        public static string GetEffectPath(int effect)
        {
            return Instance.GetRpgResourceFullPath(Instance.GetResConfigId(EPveResType.SkillEffect, effect), false);
        }



        public static GgameSceneConfig GetPveSceneConfig()
        {
            return instance._sceneResourceManager.GetSceneConfig();
        }

        public static Material GetPhantomMat()
        {
            Material mat;
            if (instance.matDic.TryGetValue((int) EPveMaterialType.phantom, out mat))
            {
                return Material.Instantiate(mat);
            }
            return null;
        }
        
        
        public Material GetBlackScreenMat()
        {
            Material mat;
            matDic.TryGetValue((int)EPveMaterialType.blackScreenMat, out mat);
            return mat;
        }

        public PveMapData GetPveMapData(int index)
        {
            return pveMapDataDic[index];
        }

        public RpgLevelData GetRpgLevelDat(int index)
        {
            return rpgLevelDataDic[index];
        }

        public Texture2D GetMiniMapTexture()
        {
            return miniMapTexture;
        }

        public GameObject GetMapShaderSetting()
        {
            return shaderSetting;
        }

        public static GameObject GetPveSceneMapPrefab()
        {
            return instance._sceneResourceManager.sceneRoot;
        }
        public static GameObject GetPveSceneMapPrefab(int part)
        {
            return instance._sceneResourceManager.GetPveSceneMapPrefab(part);
        }

        public static void RecoverPveSceneMapPrefab(GameObject prefab, int id, int part)
        {
            instance._sceneResourceManager.RecoverPveSceneMapPrefab(prefab, part);
        }
        public GameObject GetPathPoints()
        {
            return instance._sceneResourceManager.GetPathPoints();
        }

        public void ClearPathPoints()
        {
            instance._sceneResourceManager.ClearPathPoints();
        }
        
        public void RecoverPathPoints(GameObject prefab)
        {
            instance._sceneResourceManager.RecoverPathPoints(prefab);
        }

        public static List<PveSceneResourceManager.PveSceneGpuData> GetPveSceneGpuData()
        {
            return instance._sceneResourceManager.GetPveSceneGpuData();
        }

        public static GameObject GetPostProcessCamera()
        {
            return instance._sceneResourceManager.GetPostProcessCamera();
        }

        public static GameObject GetSkyBoxObject()
        {
            return instance._sceneResourceManager.GetSkyBoxObject();
        }

        public static List<Texture2D> GetLightMapColor()
        {
            return instance._sceneResourceManager.GetLightMapColor();
        }

        public static List<Texture2D> GetLightMapDir()
        {
            return instance._sceneResourceManager.GetLightMapDir();
        }

        public static GameObject GetResource(EPveResType type, int id)
        {
            var obj = ResidentHandler.Inst.GetFunction("L_RpgManager.GetResource").Func<int,int,GameObject>((int)type, id);
            if (obj == null)
            {
                return Instance.resourcePool.GetResource((int) type * 10000000 + id);
            }
            return obj;
        }
        
        public static bool IsResReady(EPveResType type, int id)
        {
            return Instance.resourcePool.IsResReady((int) type * 10000000 + id);
        }


        /// <summary>
        /// 动态加载对象池
        /// </summary>
        /// <param name="type">资源类型</param>
        /// <param name="subid">资源子id</param>
        /// <param name="action"></param>

        public static void LoadResource(EPveResType type, int subid,Action<GameObject> action)
        {
            var id = Instance.GetResConfigId(type, subid);
            var cfg = PveUtils.GetRpgResourceConfig(id);
            if (cfg !=null)
            {
                var path = Instance.GetRpgResourceFullPath(cfg, false);
                Instance.resourcePool.AddResourceAndLoad(id, path, cfg.poolNum, type, action);
            }
            else
            {
                Debug.LogError("不存在此资源Id" + id);
            }
        }
        public static object GetAsset(EPveResType type, int id)
        {
            return instance.resourcePool.GetAsset(instance.GetResConfigId(type, id));
        }

        public static Material GetWireMat()
        {
            Material mat;
            Instance.matDic.TryGetValue((int)EPveMaterialType.modelWireMat, out mat);
            return Object.Instantiate(mat);
        }

        public static Material GetDeadDissolveMat()
        {
            Material mat;
            Instance.matDic.TryGetValue((int)EPveMaterialType.deadDissolveMat, out mat);
            return Object.Instantiate(mat);
        }

        public static void RecoverResource(GameObject go, EPveResType type, int id)
        {
            ResidentHandler.Inst.GetFunction("L_RpgManager.RecoverResource").Action(go,(int)type,id);
            return;
            if (instance == null)
            {
                return;
            }
            
            int resId = instance.GetResConfigId(type,id);
            instance.resourcePool.RecoverResource(resId, go);
        }

        public string GetRpgResourceFullPath(int sourceId, bool needSuffix = true)
        {
            var resourceCfg = PveUtils.GetRpgResourceConfig(sourceId);
            return GetRpgResourceFullPath(resourceCfg, needSuffix);
        }

        public string GetRpgResourceFullPath(RpgResourceConfig config, bool needSuffix = true)
        {
            var path = config.path;
            if (needSuffix)
            {
                switch (config.restype)
                {
                    case 1:
                        path = $"{path}.prefab";
                        break;
                    case 2:
                        path = $"{path}.mat";
                        break;
                    case 3:
                        path = $"{path}.asset";
                        break;
                    case 4:
                        path = $"{path}.png";
                        break;
                    case 5:
                        path = $"{path}.tga";
                        break;
                }
            }

            return path;
        }

        public void Dispose()
        {
            _sceneResourceManager.Dispose();
            
            resourcePool.Dispose();
            foreach (var item in matDic)
            {
                Object.DestroyImmediate(item.Value);
            }

            _resLoader?.Recycle2Cache();
            _resLoader = null;
            matResLoader?.Recycle2Cache();
            matResLoader = null;
            mapLoader?.Recycle2Cache();
            mapLoader = null;
            pathMgrLoader?.Recycle2Cache();
            pathMgrLoader = null;
            PeopleResLoader?.Recycle2Cache();
            PeopleResLoader = null;

            for (int i = 0; i < lightMapLoader.Count; i++)
            {
                lightMapLoader[i].Recycle2Cache();
            }

            lightMapLoader.Clear();
            isLoadedMap = false;
            isLoadedMat = false;
            matDic.Clear();
            Object.DestroyImmediate(resRoot);
            resRoot = null;
            instance = null;
       
            if (aStarRoot!=null)
            {
                Object.DestroyImmediate(aStarRoot);
                aStarRoot = null;
            }
            
            ResidentHandler.Inst.RemoveFunction("L_RpgManager.GetResource");
            ResidentHandler.Inst.RemoveFunction("L_RpgManager.RecoverResource");
        }

        public void StartLoad(Action onLoadOver)
        {
            //IsReady = false;
            loadStartTime = TimeManager.logicTime;
            //LoadNext(onLoadOver);
            resourcePool.Preload(() =>
            {
                onLoadOver?.Invoke();
            });
        }

        private void LoadMapData(Action onLoadOverAction)
        {
            _sceneResourceManager.LoadScene(30000000, resRoot, onLoadOverAction, true);
        }

        private void LoadMaterials(Action onLoadOver)
        {
            if (matResLoader != null)
            {
                onLoadOver?.Invoke();
                return;
            }

            if (isLoadedMat)
            {
                onLoadOver?.Invoke();
                return;
            }

            isLoadedMat = true;
            matResLoader = ResLoader.Alloc();
            var list = PveUtils.GetRpgResourceConfigListByType(EPveResType.Mat);
            foreach (var config in list)
            {
                var path = GetRpgResourceFullPath(config);
                matResLoader.Add2Load(path, (success, assetName, asset) =>
                {
                    if (success)
                    {
                        var mat = Object.Instantiate(asset as Material);
                        if (!matDic.ContainsKey(config.subid))
                        {
                            matDic.Add(config.subid, mat);
                        }
                    }
                });
            }
            matResLoader.Load(onLoadOver);
        }
        
        private void PreloadCamera(Action action = null)
        {
            //resourcePool.AddResource(130000010, "Assets/ResourcesAssets/Pve/Prefabs/Camera/PveCamera", 1,
            //    EPveResType.Camera);
            if (camera != null && rpgCamera != null)
            {
                action?.Invoke();
                return;
            }
            var config = PveUtils.GetRpgResourceConfig(130000010);
            var path = GetRpgResourceFullPath(config);
            camResLoader = ResLoader.Alloc();

            camResLoader.Add2Load(path, (success, name, asset) =>
            {
                if (success)
                {
                    if (!success)
                    {
                        Debug.LogError(path + "加载失败");
                        return;
                    }
                    var obj = GameObject.Instantiate(asset as GameObject);
                    camera = obj as GameObject;
                    // var dynamicMeshBuildier = camera.AddComponent<DynamicNavMeshBuilder>();
                   // dynamicMeshBuildier.m_Size = new Vector3(400,30,400);
                }
            });
            config = PveUtils.GetRpgResourceConfig(130000011);
            path = GetRpgResourceFullPath(config);
            camResLoader.Add2Load(path, ((success, name, asset) =>
            {
                if (success)
                {
                    if (!success)
                    {
                        Debug.LogError(path + "加载失败");
                        return;
                    }
                    var obj = GameObject.Instantiate(asset as GameObject);
                    rpgCamera = obj as GameObject;
                    rpgCamera.SetActive(false);
                    // var dynamicMeshBuildier = camera.AddComponent<DynamicNavMeshBuilder>();
                    // dynamicMeshBuildier.m_Size = new Vector3(400,30,400);
                }
            }));

            camResLoader.Load(action);
        }
        private void PreloadPathManager(Action action)
        {
            action.Invoke();
            // if (pathMgrLoader != null)
            // {
            //     action?.Invoke();
            //     return;
            // }
            // pathMgrLoader = ResLoader.Alloc();
            // pathMgrLoader.Add2Load("Assets/ResourcesAssets/Pve/Prefabs/Traffic/AITrafficController.prefab", ((success, name, asset) =>
            // {
            //     if (success)
            //     {
            //         if (!success)
            //         {
            //             Debug.LogError( "AITrafficController加载失败");
            //             return;
            //         }
            //         var obj = GameObject.Instantiate(asset as GameObject);
            //         obj.GetComponent<AITrafficController>().centerPoint = camera.transform;
            //         trafficObj = obj;
            //     }
            // }));
            //
            // pathMgrLoader.Add2Load("Assets/ResourcesAssets/Pve/Prefabs/AI/RPGTreeBehaviors.prefab", ((success, name, asset) =>
            // {
            //     if (success)
            //     {
            //         if (!success)
            //         {
            //             Debug.LogError("RPGTreeBehaviors加载失败");
            //             return;
            //         }
            //         var tree= GameObject.Instantiate(asset as GameObject);
            //         tree.AddComponent<BehaviorDesigner.Runtime.BehaviorManager>();
            //         behaviorsObj = tree;
            //     }
            // }));
            //
            // pathMgrLoader.Load(action);
        }
        private void PreloadDirector()
        {
            var list = PveUtils.GetRpgResourceConfigListByType(EPveResType.Director);
            foreach (var config in list)
            {
                string path = GetRpgResourceFullPath(config, false);
                TryAddToRpgBattleNewResource(config.id);
                resourcePool.AddResource(config.id, path, config.poolNum, EPveResType.Director);
            }
        }

        private void PreloadUI()
        {
            var list = PveUtils.GetRpgResourceConfigListByType(EPveResType.UI);
            foreach (var config in list)
            {
                string path = GetRpgResourceFullPath(config, false);
                TryAddToRpgBattleNewResource(config.id);
                resourcePool.AddResource(config.id, path, config.poolNum, EPveResType.UI);
            }
        }

        private void PreloadDrop()
        {
            resourcePool.AddResource(70000000, "Assets/ResourcesAssets/Pve/Prefabs/Others/stacks", 100,
                EPveResType.Drop,
                (o) => { o.transform.localScale = PveUtils.globalRatio * o.transform.localScale; });
            resourcePool.AddResource(70000001, "Assets/ResourcesAssets/Pve/Prefabs/Others/Health_Crate1", 10,
                EPveResType.Drop,
                (o) => { o.transform.localScale = PveUtils.globalRatio * o.transform.localScale; });
            resourcePool.AddResource(70000002, "Assets/ResourcesAssets/Pve/Prefabs/Others/Medic_Bag1", 10,
                EPveResType.Drop,
                (o) => { o.transform.localScale = PveUtils.globalRatio * o.transform.localScale; });
        }

        private void PreloadBullet()
        {
            var list = PveUtils.GetRpgResourceConfigListByType(EPveResType.Bullet);
            foreach (var config in list)
            {
                string path = GetRpgResourceFullPath(config, false);
                resourcePool.AddResource(config.id, path, config.poolNum, EPveResType.Bullet,
                    (o) => { o.transform.localScale = PveUtils.globalRatio * o.transform.localScale; });
            }
        }

        private void PreloadSkillEffects()
        {

            var list = PveUtils.GetRpgResourceConfigListByType(EPveResType.SkillEffect);
            foreach (var config in list)
            {
                string path = GetRpgResourceFullPath(config, false);
                    resourcePool.AddResource(config.id, path, config.poolNum, EPveResType.SkillEffect);
            }
        }

        private void PreloadPointer()
        {
            var list = PveUtils.GetRpgResourceConfigListByType(EPveResType.Pointer);
            foreach (var config in list)
            {
                string path = GetRpgResourceFullPath(config, false);
                TryAddToRpgBattleNewResource(config.id);
                resourcePool.AddResource(config.id, path, config.poolNum, EPveResType.Pointer,
                    (o) => { o.transform.localScale = PveUtils.globalRatio * 0.25f * new Vector3(1, 1, 1); });
            }
        }

        private void PreloadMap(Action onLoadOver)
        {
            if (isLoadedMap)
            {
                onLoadOver?.Invoke();
                return;
            }

            isLoadedMap = true;

            mapLoader = ResLoader.Alloc();
            for (int i = 0; i < 6; i++)
            {
                int index = i;//这是啥，有必要加载6个关卡么
                mapLoader.Add2Load($"Assets/ResourcesAssets/Pve/Data/level{i}.asset", (s, n, a) =>
                {
                    if (!s)
                    {
                        return;
                    }

                    rpgLevelDataDic.Add(index, a as RpgLevelData);
                });
            }

            for (int i = 101; i < 102; i++)
            {
                int index = i;
                mapLoader.Add2Load($"Assets/ResourcesAssets/Pve/Data/level{i}.asset", (s, n, a) =>
                {
                    if (!s)
                    {
                        return;
                    }

                    rpgLevelDataDic.Add(index, a as RpgLevelData);
                });
            }

            mapLoader.Add2Load("Assets/ResourcesAssets/Pve/Data/PveMap0.asset", (s, n, a) =>
            {
                if (!s)
                {
                    return;
                }

                pveMapDataDic.Add(0, a as PveMapData);
            });
            mapLoader.Add2Load("Assets/ResourcesAssets/Pve/Data/PveMap1.asset", (s, n, a) =>
            {
                if (!s)
                {
                    return;
                }

                pveMapDataDic.Add(1, a as PveMapData);
            });
            mapLoader.Add2Load("Assets/ResourcesAssets/Pve/Data/PveMap5.asset",(s, n, a) =>
            {
                if (!s)
                {
                    return;
                }
                pveMapDataDic.Add(5,a as PveMapData);
            });
            /*mapLoader.Add2Load("Assets/ResourcesAssets/Pve/Textures/pveMiniMap0.png", (s, n, a) =>
            {
                if (!s)
                {
                    return;
                }

                //todo
                miniMapTexture = a as Texture2D;
            });*/
            /*mapLoader.Add2Load("Assets/ResourcesAssets/Pve/Prefabs/Others/SkyBoxBg.prefab", (s, n, a) =>
            {
                skyBox = GameObject.Instantiate(a as GameObject);
            });*/
//            mapLoader.Add2Load("Assets/ResourcesAssets/Pve/Prefabs/Others/ShaderSetting.prefab", (s, n, a) =>
//            {
//                if (!s)
//                {
//                    return;
//                }
//
//                shaderSetting = Object.Instantiate(a as GameObject);
//            });

            mapLoader.Add2Load("Assets/ResourcesAssets/Prefabs/NpcFramework/Astar.prefab", (success, name, asset) =>
            {
                if (!success)
                {
                    return;   
                }

                aStarRoot = GameObject.Instantiate(asset as GameObject);
            });
            
            mapLoader.Add2Load("Assets/ResourcesAssets/Prefabs/NpcFramework/PveNpcFrameworkMgr.prefab", (success, name, asset) =>
            {
                if (!success)
                {
                    return;   
                }

                pveNpcFrameworkMgrObj = GameObject.Instantiate(asset as GameObject);

                lightingObj = HRenderSceneManager.RenderSceneCache.PveRenderScene.gameObject;
                shaderSetting = lightingObj.transform.Find("ShaderSetting").gameObject;
                postEffectObj = lightingObj.GetComponentInChildren<Volume>();
            });

            mapLoader.Add2Load("Assets/ResourcesAssets/Prefabs/NpcFramework/TrafficLight.prefab",
                (success, name, asset) =>
                {
                    if (!success)
                    {
                        return;
                    }

                    pveTrafficLight = GameObject.Instantiate(asset as GameObject);

                });
            mapLoader.Load(()=>
            {
                // PveManager.Instance.PveNpcFrameworkMgr = pveNpcFrameworkMgrObj.GetComponent<NpcFrameworkMgr>();
                // PveManager.Instance.InitNpcFramework();
                // RPGTreeBehaviors rpgTreeBehaviors = pveNpcFrameworkMgrObj.GetComponentInChildren<RPGTreeBehaviors>();
                // rpgTreeBehaviors.OnInit();
                // PveSceneResourceManager.sceneSeparateMgr.InitNpcFramework(PveManager.Instance.PveNpcFrameworkMgr);
                //
                // NFMgr.TrafficManager.OnInit(pveTrafficLight);
                
                onLoadOver?.Invoke();
            });
        }

        private void PreloadHud()
        {
            Material mat;
            matDic.TryGetValue((int)EPveMaterialType.overlayMat, out mat);
            var list = PveUtils.GetRpgResourceConfigListByType(EPveResType.Hud);
            foreach (var config in list)
            {
                string path = GetRpgResourceFullPath(config, false);
                TryAddToRpgBattleNewResource(config.id);
                resourcePool.AddResource(config.id, path, config.poolNum, EPveResType.Hud,
                    (o) =>
                    {
                        //RTSLuaCallCSharpManager.SetUIOverlayMat(o, mat);
                    });
            }
        }

        
        public static Material GetSkyBoxMaterial()
        {
            return instance._sceneResourceManager.GetSkyBoxMaterial();
        }

        public static Color GetAmbientColor()
        {
            return instance._sceneResourceManager.GetAmbientColor();
        }
        public static DefaultReflectionMode GetReflectionMode()
        {
            return instance._sceneResourceManager.GetReflectionMode();
        }

        public static Cubemap GetReflectionProbe()
        {
            return instance._sceneResourceManager.GetReflectionProbe();
        }

        public void UnloadPveResource()
        {
            _sceneResourceManager.UnloadPveResource();
        }
        public class PveResPoolData
        {
            public int id;
            public string path;
            public List<GameObject> objPool;
            public List<GameObject> objTotalPool;
            public int poolNum;
            public Action<GameObject> onLoadOver;
            public bool isLoaded;
            public EPveResType type;
        }

        public class PveResourcePool
        {
            public ResLoader _resLoader;
            private Dictionary<int, object> assetPoolDic = new Dictionary<int, object>(128);
            public bool loadComplete;
            private Dictionary<int, PvePrefabPool> objPoolDic = new Dictionary<int, PvePrefabPool>(32);
            private Transform root;
            public EPveResType type;

            public void Initialize(EPveResType type, Transform root, ResLoader loader)
            {
                this.type = type;
                this.root = root;
                _resLoader = loader;
                loadComplete = false;
            }

            public void AddAsset(int id, string path, Action<object> onLoadOver = null)
            {
                _resLoader.Add2Load(path, (success, name, asset) =>
                {
                    if (!success)
                    {
                        return;
                    }

                    onLoadOver?.Invoke(asset);
                    if (!assetPoolDic.ContainsKey(id))
                    {
                        assetPoolDic.Add(id, asset);
                    }
                });
            }

            public object GetAsset(int id)
            {
                assetPoolDic.TryGetValue(id, out var obj);
                return obj;
            }

            public bool IsResReady(int id)
            {
                if (objPoolDic.TryGetValue(id, out var pool) && pool.IsLoaded)
                {
                    return true;
                }
                return false;
            }

            public void UnloadRes(int id)
            {
                if (objPoolDic.TryGetValue(id, out var pool))
                {
                    if (pool.IsLoaded)
                    {
                        pool.Destroy();
                        objPoolDic.Remove(id);
                    }
                }
            }
            
            public void AddResource(int id, string path, int poolNum, EPveResType type,
                Action<GameObject> onLoadOver = null)
            {
                if (!objPoolDic.ContainsKey(id))
                {
                    PvePrefabPool item = null;
                    if (type == EPveResType.Npc || type == EPveResType.Car)
                    {
                        item = new PveNpcPool(type,poolNum,poolNum,path + ".prefab",root,onLoadOver);
                    }
                    else
                    {
                        item = new PvePrefabPool(type,poolNum,poolNum,path + ".prefab",root,onLoadOver);
                    }
                    
                    objPoolDic.Add(id, item);
                }
            }

            public bool HasRegister(int resId)
            {
                return objPoolDic.ContainsKey(resId);
            }

            public GameObject GetResource(int id)
            {
                if (objPoolDic.ContainsKey(id))
                {
                    var pool = objPoolDic[id];
                    return pool.GetItem();
                }

#if UNITY_EDITOR
                Debug.LogError("id为" + id + "的资源找不到");
#else
                Debug.Log("id为" + id + "的资源找不到");
#endif
                return null;
            }

            public void RecoverResource(int id, GameObject obj)
            {
                if (obj == null) {
                    return;
                }

                if (objPoolDic.ContainsKey(id))
                {
                    objPoolDic[id].RecoverItem(obj);
                }
            }

            public void Preload(Action loaded)
            {
                int loadedCount = 0;
                foreach (var item in objPoolDic.Values)
                {
                    item.PreLoad((o =>
                    {
                        loadedCount++;
                        if (loadedCount == objPoolDic.Count)
                        {
                            loaded?.Invoke();
                        }
                    }));
                    
                    
                    
//                           //因为编辑器下会调用loading.checkconsistency,如果不提前setactive会造成游戏中卡顿
//#if UNITY_EDITOR
//                            if (item.type == EPveResType.Model)
//                            {
//                                for (int i = 0; i < newList.Count; i++)
//                                {
//                                    newList[i].transform.position = new Vector3(-999,0,-999);
//                                }
//                                //item.onLoadOver?.Invoke(o);
//                                int itemId = item.id;
//                                TimeManager.Instance.DelayCall(2000, () =>
//                                {
//                                    for (int i = 0; i < objPoolDic[itemId].objPool.Count; i++)
//                                    {
//                                        objPoolDic[itemId].objPool[i].SetActive(false);
//                                        objPoolDic[itemId].objPool[i].transform.SetParent(root);
//                                    }
//                                });
//                                return;
//                            }
//#endif

                }
            }

            public void AddResourceAndLoad(int id,string path,int poolNum,EPveResType type,Action<GameObject> onLoadOver = null)
            {
                if (!objPoolDic.ContainsKey(id))
                {
                    PvePrefabPool item = null;
                    if (type == EPveResType.Npc || type == EPveResType.Car)
                    {
                        item = new PveNpcPool(type,poolNum,poolNum,path + ".prefab",root,onLoadOver);
                    }
                    else
                    {
                        item = new PvePrefabPool(type,poolNum,poolNum,path + ".prefab",root,onLoadOver);
                    }
                    objPoolDic.Add(id, item);
                    item.PreLoad(null);
                }
                else
                {
                    objPoolDic[id].AddCallBack(onLoadOver);
                }
            }

            public void Load(Action action)
            {
                _resLoader.Load(() =>
                {
                    loadComplete = true;
                    action?.Invoke();
                });
            }

            public void Dispose()
            {
                foreach (var item in objPoolDic.Values)
                {
                   item.Destroy();
                }
                objPoolDic.Clear();
                assetPoolDic.Clear();
                _resLoader.Recycle2Cache();
                _resLoader = null;
            }
            
            
        }
        private enum EPveMaterialType
        {
            blackScreenMat = 1,
            overlayMat = 2,
            modelShadowMat = 3,
            modelFlashMat = 4,
            modelWireMat = 5,
            deadDissolveMat = 6,
            phantom = 7,
        }
    }
}
